package com.tecnap.app.database;

import java.util.ArrayList;
import java.util.List;

import com.tecnap.app.LampEntity;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;

public class LampDataSource extends DataSource {

	public LampDataSource(Context context) {
		super(context);
	}
	
	/**
	 * Execute query to find associated lamp for a certain ID
	 * and return the object representation of it
	 * (see: com.tecnap.app.LampEntity)
	 * 
	 * @param id
	 * @return LampEntity
	 */
	public LampEntity getLampByID(int id) {
		Cursor cursor = database.query(
				DatabaseHelper.TABLE_LAMP,
				null, "lamp" + DatabaseHelper.COLUMN_ID + " = ?",	
				new String[] { Integer.toString(id) },
				null, null,	null );
		
		if (cursor.moveToFirst()) 
			return cursorToLamp(cursor);
		
		return null;
	}
	
	/**
	 * Execute query to find associated lamp for a certain Number
	 * and return the object representation of it
	 * (see: com.tecnap.app.LampEntity)
	 * 
	 * @param number
	 * @return LampEntity
	 */
	public LampEntity getLampByNumber(String number) {
		Cursor cursor = database.query(
				DatabaseHelper.TABLE_LAMP,
				null, "number = ?",	
				new String[] { number },
				null, null,	null );
		
		if (cursor.moveToFirst()) 
			return cursorToLamp(cursor);
		
		return null;
	}
	
	/**
	 * Returns a list of all lamps stored into db
	 * @return List<LampEntity>
	 */
	public List<LampEntity> getAllLamps() {
		List<LampEntity> lamps = new ArrayList<LampEntity>();
		
		Cursor cursor = database.query(DatabaseHelper.TABLE_LAMP, 
				null, null, null, null, null, "lamp" + DatabaseHelper.COLUMN_ID + " DESC" );
		cursor.moveToFirst();
		
		while (!cursor.isAfterLast()) {
			LampEntity lamp = cursorToLamp(cursor);
			lamps.add(lamp);
			cursor.moveToNext();
		}
		
		cursor.close();
		return lamps;
	}
	
	/**
	 * Create or Update a new Lamp into DB
	 * @param ID
	 * @param number
	 * @param type
	 * @param brand
	 * @param power
	 * @param model
	 * @param comment
	 * @param positionX
	 * @param positionY
	 */
	public void setLamp( int ID, String number, String type, String brand, String power,
			String model, String comment, float positionX, float positionY ) throws Exception {
		
		// Il numero lampada deve essere compilato
		if( number.length() == 0 || number == null )
			throw new Exception("Il numero lampada è obbligatorio");
		
		// Altrimenti crea l'oggeto e aggiungilo/modificalo nel DB
		LampEntity lamp = new LampEntity( ID, number, type, brand, power, model, comment,
				positionX, positionY );
		
		setLamp(lamp);
	}
	
	/**
	 * Create or Update a new lamp into DB
	 * @param lamp
	 */
	public void setLamp(LampEntity lamp) {
		// Values container
		ContentValues values = new ContentValues();
		values.put("number", lamp.getNumber());
		values.put("type", lamp.getType());
		values.put("brand", lamp.getBrand());
		values.put("power", lamp.getPower());
		values.put("model", lamp.getModel());
		values.put("comment", lamp.getComment());
		values.put("X", lamp.getPositionX());
		values.put("Y", lamp.getPositionY());
		
		// Check if the lamp already exists
		if ( getLampByNumber(lamp.getNumber()) == null ) {
			database.insert(DatabaseHelper.TABLE_LAMP, null, values);
		} else {
			// Else update it
			database.update(DatabaseHelper.TABLE_LAMP, values, "lamp" + DatabaseHelper.COLUMN_ID + " = ?",
					new String[] { Integer.toString(lamp.getID()) });
		}
	}
	
	/**
	 * Delete a lamp from table "lamp"
	 * @param id
	 * @return boolean : true if the record is deleted, false otherwise
	 */
	public boolean removeLampByID( int id ) {
		LampEntity lamp = getLampByID(id);
		
		if ( lamp == null )
			return false;
		
		if ( database.delete(
				DatabaseHelper.TABLE_LAMP,
				"lamp" + DatabaseHelper.COLUMN_ID + " = ?",
				new String[] { Integer.toString(id) }) != 0 )
			return true;
		
		return false;
	}
	
	/**
	 * Delete a lamp from table "lamp"
	 * @param Number
	 * @return boolean : true if the record is deleted, false otherwise
	 */
	public boolean removeLampByNumber( String number ) {
		LampEntity lamp = getLampByNumber(number);
		
		if ( lamp == null )
			return false;
		
		if ( database.delete(
				DatabaseHelper.TABLE_LAMP,
				"number = ?",
				new String[] { number }) != 0 )
			return true;
		
		return false;
	}
	
	/**
	 * Used to delete all lamps stored into db
	 */
	public boolean removeAll() {
		if ( database.delete(DatabaseHelper.TABLE_LAMP,	null, null) != 0 )
			return true;
		
		return false;
	}
	
	/**
	 * Return a new LampEntity object from a cursor
	 * 
	 * @param cursor
	 * @return LampEntity
	 */
	private LampEntity cursorToLamp(Cursor cursor) {
		return new LampEntity(
				cursor.getInt(0), 		// ID
				cursor.getString(1),	// Number
				cursor.getString(2),	// Type
				cursor.getString(3),	// Brand
				cursor.getString(4),	// Power
				cursor.getString(5),	// Model
				cursor.getString(6),	// Comment
				cursor.getFloat(7),		// X
				cursor.getFloat(8)		// Y
				);
	}
	
	/**
	 * Return min & max of Lat & Lon of Lamps in a Float[] Array
	 * This method is used to calculate the area to be shown in the map, including all the lamps in database
	 * 
	 * @return Float[] Array of map markers boundaries 
	 */
	public Float[] getMapBoundaries(){
		
		Float[] boundaries = {new Float(0.0),new Float(0.0),new Float(0.0),new Float(0.0)};
		Cursor cursor1, cursor2, cursor3, cursor4;
		
		cursor1 = database.rawQuery("SELECT min(X) FROM "+DatabaseHelper.TABLE_LAMP+" ", new String[] {});
		if (cursor1.moveToFirst()) boundaries[0] = cursor1.getFloat(0);
		cursor1.close();
		
		cursor2 = database.rawQuery("SELECT max(X) FROM "+DatabaseHelper.TABLE_LAMP+" ", new String[] {});
		if (cursor2.moveToFirst()) boundaries[1] = cursor2.getFloat(0);
		cursor2.close();
		
		cursor3 = database.rawQuery("SELECT min(Y) FROM "+DatabaseHelper.TABLE_LAMP+" ", new String[] {});
		if (cursor3.moveToFirst()) boundaries[2] = cursor3.getFloat(0);
		cursor3.close();
		
		cursor4 = database.rawQuery("SELECT max(Y) FROM "+DatabaseHelper.TABLE_LAMP+" ", new String[] {});
		if (cursor4.moveToFirst()) boundaries[3] = cursor4.getFloat(0);
		cursor4.close();
		
		return boundaries;
	}
}
